
/*******************************************************************************
  Application Source File

  Company:
    Microchip Technology Inc.

  File Name:
    app_ecdsa.c

  Summary:
    This source file handles the running of the ECDSA application.
*******************************************************************************/

/*
Copyright (C) 2025, Microchip Technology Inc., and its subsidiaries. All rights reserved.

The software and documentation is provided by microchip and its contributors
"as is" and any express, implied or statutory warranties, including, but not
limited to, the implied warranties of merchantability, fitness for a particular
purpose and non-infringement of third party intellectual property rights are
disclaimed to the fullest extent permitted by law. In no event shall microchip
or its contributors be liable for any direct, indirect, incidental, special,
exemplary, or consequential damages (including, but not limited to, procurement
of substitute goods or services; loss of use, data, or profits; or business
interruption) however caused and on any theory of liability, whether in contract,
strict liability, or tort (including negligence or otherwise) arising in any way
out of the use of the software and documentation, even if advised of the
possibility of such damage.

Except as expressly permitted hereunder and subject to the applicable license terms
for any third-party software incorporated in the software and any applicable open
source software license terms, no license or other rights, whether express or
implied, are granted under any patent or other intellectual property rights of
Microchip or any third party.
*/

/* cppcheck-suppress misra-c2012-21.6
* 
*  (Rule 21.6) Required: The standard library input/output functions shall not be used
* 
*  Reasoning: This demo uses printf to print out information to a terminal.
*/
#include <stdio.h>
#include "app_ecdsa.h"
#include "crypto/common_crypto/crypto_digsign.h"

#define RESET_COLOR     "\033""[0m"
#define RED             "\033""[1;31m"
#define GREEN           "\033""[1;32m"
#define YELLOW          "\033""[1;33m"
#define BLUE            "\033""[1;34m"
#define MAG             "\033""[1;35m"
#define CYAN            "\033""[1;36m"
#define SESSION_ID      0x1U

static const char * signaturePrint = "Signature : \t";
static const char * signing = "SIGN";
static const char * verifying = "VERIFY";

static inline void printStatus(crypto_DigiSign_Status_E status, const char *type)
{
    if(status != CRYPTO_DIGISIGN_SUCCESS)
    {
        (void)printf(RED" \r\n ECDSA %s FAIL:: ErrorCode = 0x%X"RESET_COLOR, type, (unsigned int) status);
    }
    else
    {
        (void)printf(GREEN" \r\n ECDSA %s PASS "RESET_COLOR, type);
    }
}

static inline void printSplitter(void)
{
    (void)printf("\r\n\n ______________________________________________________________________________________________________ \r\n");
}

static inline void printTestHeader(const char* label)
{
    (void)printf(MAG"\r\n\r\n ************************************************************************************");
    (void)printf(CYAN"\r\n\t\t ******************** %s ********************", label);
    (void)printf(MAG"\r\n ************************************************************************************"RESET_COLOR);
}

static inline void printHexArray(const char* label, void* Data, uint32_t size) 
{
    (void)printf(BLUE"\r\n --------------------------------------------------------------------------------------------------"RESET_COLOR);
    uint8_t *ldata = (uint8_t *) Data;
    (void)printf("\r\n %s", label);
    for (uint32_t i = 0; i < size; i++) 
    {
        if (0U == i % 16U && 0U != i) 
        {
            (void)printf("\r\n\t\t");
        }
        
        (void)printf(" 0x%02X", ldata[i]);
    }
}

static inline void runHardwareTest(uint8_t *hash, uint32_t hashLength, 
        uint8_t *signature, uint32_t signatureLength, uint8_t *publicKey, uint32_t publicKeyLength,
        uint8_t *privateKey, uint32_t privateKeyLength, crypto_EccCurveType_E eccCurveType)
{
    
    int8_t hashStatus = 0;   
    crypto_DigiSign_Status_E status = CRYPTO_DIGISIGN_SUCCESS;
    
    ////Crypto Library ECDSA SIGN***********************************************************************************************************************
    status = Crypto_DigiSign_Ecdsa_Sign(CRYPTO_HANDLER_HW_INTERNAL, hash, hashLength, signature, signatureLength, privateKey, privateKeyLength, eccCurveType, SESSION_ID);
    
    printStatus(status, signing);
    
    printHexArray(signaturePrint, signature, signatureLength);
    
    ////Crypto Library ECDSA VERIFY*********************************************************************************************************************
    status = Crypto_DigiSign_Ecdsa_Verify(CRYPTO_HANDLER_HW_INTERNAL, hash, hashLength, signature, signatureLength, publicKey, publicKeyLength, &hashStatus, eccCurveType, SESSION_ID);
    
    printStatus(status, verifying);
}

static void TEST_ECDSA_p192(void) 
{
    printTestHeader("P-192 ECDSA");

     ////NIST Defined Private Key********************************************************************************************
    uint8_t testPrivateKey[24] = {
        0xe5, 0xce, 0x89, 0xa3, 0x4a, 0xdd, 0xdf, 0x25, 0xff, 0x3b, 0xf1, 0xff, 
        0xe6, 0x80, 0x3f, 0x57, 0xd0, 0x22, 0x0d, 0xe3, 0x11, 0x87, 0x98, 0xea
    };
    
    ////NIST Defined Public Key**********************************************************************************************
    uint8_t testPublicKey[49] = {
        0x04, 0x8a, 0xbf, 0x7b, 0x3c, 0xeb, 0x2b, 0x02, 0x43, 0x8a, 0xf1, 0x95, 
        0x43, 0xd3, 0xe5, 0xb1, 0xd5, 0x73, 0xfa, 0x9a, 0xc6, 0x00, 0x85, 0x84, 
        0x0f, 0xa8, 0x7f, 0x80, 0x18, 0x2d, 0xcd, 0x56, 0xa6, 0xa0, 0x61, 0xf8, 
        0x1f, 0x7d, 0xa3, 0x93, 0xe7, 0xcf, 0xfd, 0x5e, 0x07, 0x38, 0xc6, 0xb2, 
        0x45
    };

    uint8_t signature[48] = {0};

    uint8_t hash[32] = {
        0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde,
        0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
        0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad
    };
    
    runHardwareTest(hash, sizeof(hash), signature, sizeof(signature), testPublicKey, sizeof(testPublicKey), testPrivateKey, sizeof(testPrivateKey), CRYPTO_ECC_CURVE_P192);
}

static void TEST_ECDSA_p256(void) 
{
    printTestHeader("P-256 ECDSA");
    
    ////NIST Defined Private Key********************************************************************************************
    uint8_t testPrivateKey[32] = {
        0xc9, 0x80, 0x68, 0x98, 0xa0, 0x33, 0x49, 0x16, 0xc8, 0x60, 0x74, 0x88, 
        0x80, 0xa5, 0x41, 0xf0, 0x93, 0xb5, 0x79, 0xa9, 0xb1, 0xf3, 0x29, 0x34, 
        0xd8, 0x6c, 0x36, 0x3c, 0x39, 0x80, 0x03, 0x57
    };

    ////NIST Defined Public Key**********************************************************************************************
    uint8_t testPublicKey[65] = {
        0x04, 0xd0, 0x72, 0x0d, 0xc6, 0x91, 0xaa, 0x80, 0x09, 0x6b, 0xa3, 0x2f, 
        0xed, 0x1c, 0xb9, 0x7c, 0x2b, 0x62, 0x06, 0x90, 0xd0, 0x6d, 0xe0, 0x31, 
        0x7b, 0x86, 0x18, 0xd5, 0xce, 0x65, 0xeb, 0x72, 0x8f, 0x96, 0x81, 0xb5, 
        0x17, 0xb1, 0xcd, 0xa1, 0x7d, 0x0d, 0x83, 0xd3, 0x35, 0xd9, 0xc4, 0xa8, 
        0xa9, 0xa9, 0xb0, 0xb1, 0xb3, 0xc7, 0x10, 0x6d, 0x8f, 0x3c, 0x72, 0xbc, 
        0x50, 0x93, 0xdc, 0x27, 0x5f
    };

    uint8_t signature[64] = {0};

    uint8_t hash[32] = {
        0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde,
        0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
        0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad
    };
    
    runHardwareTest(hash, sizeof(hash), signature, sizeof(signature), testPublicKey, sizeof(testPublicKey), testPrivateKey, sizeof(testPrivateKey), CRYPTO_ECC_CURVE_P256);
}

static void TEST_ECDSA_p384(void) 
{
    printTestHeader("P-384 ECDSA");
    
    ////NIST Defined Private Key********************************************************************************************
    uint8_t testPrivateKey[48] = {
        0x53, 0x94, 0xf7, 0x97, 0x3e, 0xa8, 0x68, 0xc5, 0x2b, 0xf3, 0xff, 0x8d, 
        0x8c, 0xee, 0xb4, 0xdb, 0x90, 0xa6, 0x83, 0x65, 0x3b, 0x12, 0x48, 0x5d, 
        0x5f, 0x62, 0x7c, 0x3c, 0xe5, 0xab, 0xd8, 0x97, 0x8f, 0xc9, 0x67, 0x3d, 
        0x14, 0xa7, 0x1d, 0x92, 0x57, 0x47, 0x93, 0x16, 0x62, 0x49, 0x3c, 0x37
    };

    ////NIST Defined Public Key**********************************************************************************************
    uint8_t testPublicKey[97] = {
        0x04, 0xfd, 0x3c, 0x84, 0xe5, 0x68, 0x9b, 0xed, 0x27, 0x0e, 0x60, 0x1b, 
        0x3d, 0x80, 0xf9, 0x0d, 0x67, 0xa9, 0xae, 0x45, 0x1c, 0xce, 0x89, 0x0f, 
        0x53, 0xe5, 0x83, 0x22, 0x9a, 0xd0, 0xe2, 0xee, 0x64, 0x56, 0x11, 0xfa, 
        0x99, 0x36, 0xdf, 0xa4, 0x53, 0x06, 0xec, 0x18, 0x06, 0x67, 0x74, 0xaa, 
        0x24, 0xb8, 0x3c, 0xa4, 0x12, 0x6c, 0xfc, 0x4c, 0x4d, 0x1d, 0x18, 0xa4, 
        0xb6, 0xc2, 0x1c, 0x7f, 0x69, 0x9d, 0x51, 0x23, 0xdd, 0x9c, 0x24, 0xf6, 
        0x6f, 0x83, 0x38, 0x46, 0xee, 0xb5, 0x82, 0x96, 0x19, 0x6b, 0x42, 0xec, 
        0x06, 0x42, 0x5d, 0xb5, 0xb7, 0x0a, 0x4b, 0x81, 0xb7, 0xfc, 0xf7, 0x05, 
        0xa0
    };

    uint8_t signature[96] = {0};

    uint8_t hash[48] = {
        0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b, 0xb5, 0xa0, 0x3d, 0x69,
        0x9a, 0xc6, 0x50, 0x07, 0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63,
        0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed, 0x80, 0x86, 0x07, 0x2b,
        0xa1, 0xe7, 0xcc, 0x23, 0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7
    };
    
    runHardwareTest(hash, sizeof(hash), signature, sizeof(signature), testPublicKey, sizeof(testPublicKey), testPrivateKey, sizeof(testPrivateKey), CRYPTO_ECC_CURVE_P384);
}

static void TEST_ECDSA_p521(void) 
{
    printTestHeader("P-521 ECDSA");
    
    ////NIST Defined Private Key********************************************************************************************
    uint8_t testPrivateKey[66] = {
        0x01, 0x84, 0x25, 0x8e, 0xa6, 0x67, 0xab, 0x99, 0xd0, 0x9d, 0x43, 0x63, 
        0xb3, 0xf5, 0x13, 0x84, 0xfc, 0x0a, 0xcd, 0x2f, 0x3b, 0x66, 0x25, 0x8e,
        0xf3, 0x12, 0x03, 0xed, 0x30, 0x36, 0x3f, 0xcd, 0xa7, 0x66, 0x1b, 0x6a,
        0x81, 0x7d, 0xaa, 0xf8, 0x31, 0x41, 0x5a, 0x1f, 0x21, 0xcb, 0x1c, 0xda,
        0x3a, 0x74, 0xcc, 0x18, 0x65, 0xf2, 0xef, 0x40, 0xf6, 0x83, 0xc1, 0x41, 
        0x74, 0xea, 0x72, 0x80, 0x3c, 0xff
    };

    ////NIST Defined Public Key**********************************************************************************************
    uint8_t testPublicKey[133] = {
        0x04, 0x01, 0x9e, 0xe8, 0x18, 0x04, 0x8f, 0x86, 0xad, 0xa6, 0xdb, 0x86, 
        0x6b, 0x7e, 0x49, 0xa9, 0xb5, 0x35, 0x75, 0x0c, 0x36, 0x73, 0xcb, 0x61, 
        0xbb, 0xfe, 0x55, 0x85, 0xc2, 0xdf, 0x26, 0x38, 0x60, 0xfe, 0x4d, 0x8a, 
        0xa8, 0xf7, 0x48, 0x6a, 0xed, 0x5e, 0xa2, 0xa4, 0xd7, 0x33, 0xe3, 0x46, 
        0xea, 0xef, 0xa8, 0x7a, 0xc5, 0x15, 0xc7, 0x8b, 0x9a, 0x98, 0x6e, 0xe8, 
        0x61, 0x58, 0x49, 0x26, 0xce, 0x48, 0x60, 0x01, 0xb6, 0x80, 0x9c, 0x89, 
        0xc0, 0xaa, 0x7f, 0xb0, 0x57, 0xa3, 0x2a, 0xcb, 0xb9, 0xab, 0x4d, 0x7b, 
        0x06, 0xba, 0x39, 0xdb, 0xa8, 0x83, 0x3b, 0x9b, 0x54, 0x42, 0x4a, 0xdd, 
        0x29, 0x56, 0xe9, 0x5f, 0xe4, 0x8b, 0x7f, 0xbf, 0x60, 0xc3, 0xdf, 0x51, 
        0x72, 0xbf, 0x38, 0x6f, 0x25, 0x05, 0xf1, 0xe1, 0xbb, 0x28, 0x93, 0xda, 
        0x3b, 0x96, 0xd4, 0xf5, 0xae, 0x78, 0xf2, 0x54, 0x48, 0x81, 0xa2, 0x38,
        0xf7
    };

    uint8_t signature[132] = {0};

    uint8_t hash[64] = {
        0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, 0xcc, 0x41, 0x73, 0x49,
        0xae, 0x20, 0x41, 0x31, 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
        0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, 0x21, 0x92, 0x99, 0x2a,
        0x27, 0x4f, 0xc1, 0xa8, 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
        0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, 0x2a, 0x9a, 0xc9, 0x4f,
        0xa5, 0x4c, 0xa4, 0x9f
    };
    
    runHardwareTest(hash, sizeof(hash), signature, sizeof(signature), testPublicKey, sizeof(testPublicKey), testPrivateKey, sizeof(testPrivateKey), CRYPTO_ECC_CURVE_P521);
}

void test_ecdsa(void)
{
    printSplitter();
    (void)printf("\r\n Starting CRYPTO ECDSA Verify Sign program \r\n");
    TEST_ECDSA_p192();
    TEST_ECDSA_p256();
    TEST_ECDSA_p384();
    TEST_ECDSA_p521();
    printSplitter();
}